
#include "app/app_bluetooth.h"
#include <stdio.h>
#include "string.h"
#include <unistd.h>
#include "app/app_message.h"
#include "thirdparty/log.h"

//有可能传过来的数据不是一个完整的数据正  现用一个缓冲却存这当三完整的数据帧在发送
static char read_buffer[128] = {0};
//read_buffer里面的数据长度
static char read_buffer_leng = 0;
//蓝牙从另一个蓝牙接受到的数据的正头  用这个条件和别的可以判断是不是一个完整的数据帧
static unsigned char fixed_header[] = {0xF1, 0xDD};



/// @brief 等待对面的蓝牙设备回复ack
/// @param serial_device 
/// @return 
int app_bluetoorh_witeAck(SerialDevice *serial_device)
{
    char buf[4] = {0};
    //睡眠50mas 等待对方回复
    usleep(50000);
    int result = read(serial_device->super.fd,buf,4);
    //判断读取的数据是否正确
    if(result != 4)
    {
        //读取长度不正确
        log_warn("app_bluetooth_witeack write length erreo");
        return -1;
    }
    log_trace("buf = %s",buf);
    //判断是否是我们需要的数据
    if(buf[0] == 'O' && buf[1] == 'K')
    {
        //数据正确
        log_trace("app_bluetooth_witeack data erreo");
        return 0;
    }
    return -1;
}

/// @brief 从数组里删除一些我们不需要的数据
/// @param n 
/// @return 
void app_bluetoorh_ignore(int n)
{
    if(n <= 0)
    {
        log_warn("aapp_bluetoorh_ignore not data");
        return;
    }
    //read_buffer_len  长度更新
    read_buffer_leng -= n;
    //read_buffer + n 这个指针指向的数据 移到 read_buffer 里面  移动read_buffer_leng个
    memmove(read_buffer,read_buffer + n,read_buffer_leng);
}



/// @brief 检测蓝牙的状态
/// @param serial_device 
/// @return 成功0  失败-1
int app_bluetooth_status(SerialDevice *serial_device)
{
    //验证
    int result =  write(serial_device->super.fd,"AT\r\n",4);
    //判断是否成功
    if(result != 4)
    {
        //发送失败 
        log_warn("app_bluetooth_status write length erreo");
        return -1;
    }
    //等待对方回应 OK\r\n
    return app_bluetoorh_witeAck(serial_device);
}


/// @brief 设置蓝牙的波特率
/// @param serial_device 蓝牙
/// @param band 波特率
/// @return 成功0  失败-1
int app_bluetooth_setBtBuad(SerialDevice * serial_device,BT_Buad band)
{
    char buf[] = "AT+BAUD0\r\n";
    //设置波特率
    buf[7] = band;
    int result = write(serial_device->super.fd,buf,10);
    //判断发送的数据长度是否正确
    if(result != 10)
    {
        log_warn("app_bluetooth_setBtBuad write length erreo");
        return -1;
    }
    //等待应答
    return app_bluetoorh_witeAck(serial_device);
}

/// @brief 重启蓝牙设备
/// @param serial_device 
/// @return 成功0  失败-1
int app_bluetooth_reset(SerialDevice * serial_device)
{
    int result = write(serial_device->super.fd,"AT+RESET\r\n",10);
    if(result != 10)
    {
        log_warn("app_bluetooth_reset reset fail");
        return -1;
    }
    //等待回答
    return app_bluetoorh_witeAck(serial_device);
}


/// @brief 设置蓝牙的组id
/// @param serial_device 设备
/// @param id 要设置的id
/// @return 成功0  失败-1
int app_bluetooth_setId(SerialDevice * serial_device,char *id)
{
    //判读id是否正确
    if(strlen(id) != 4)
    {
        log_warn("app_bluetooth_setId id errro");
        return -1;
    }
    char buf[] = "AT+NETID0000\r\n";
    //设置id
    memcpy(buf+8,id,4);
    int result = write(serial_device->super.fd,buf,14);
    if(result != 14)
    {
        log_warn("app_bluetooth_setId id write fail");
        return -1;
    }
    return app_bluetoorh_witeAck(serial_device);
}


/// @brief 设置蓝牙的独一地址
/// @param serial_device 设备
/// @param addr 要设置的地址
/// @return 成功0  失败-1
int app_bluetooth_setAddr(SerialDevice * serial_device,char *addr)
{
    //判读id是否正确
    if(strlen(addr) != 4)
    {
        log_warn("app_bluetooth_setAddr addr length erreo");
        return -1;
    }
    char buf[] = "AT+MADDR0000\r\n";
    //设置id
    memcpy(buf+8,addr,4);
    int result = write(serial_device->super.fd,buf,14);
    if(result != 14)
    {
        log_warn("app_bluetooth_setAddr write length erreo");
        return -1;
    }
    return app_bluetoorh_witeAck(serial_device);
}

/// @brief 把设备的连接方式 和其他属性 并且测试是否能够通信
/// @param serial_device 
/// @return 
int app_bluetooth_setConnectionType(SerialDevice *serial_device)
{
    app_serial_setBlockMote(serial_device,0);  //非阻塞模式
    app_serial_setBaud(serial_device,baud_9600);  //串口端波特率9600
    app_serial_flush(serial_device);              //应用配置
    //测试是否可以通信
    if(app_bluetooth_status(serial_device) < 0)
    {
        //失败
        //表示蓝牙端是115200  串口设115200
        if(app_serial_setBaud(serial_device,Baud_115200) < 0)
        {
            log_warn("app_bluetooth_setConnectionType set serial Buad fail");
            return -1;
        }
        app_serial_flush(serial_device);              //应用配置
    }
    //再次测试 
    if(app_bluetooth_status(serial_device) < 0)
    {
         log_error("app_bluetooth_setConnectionType test fail");
         return -1;
    }
    //设置id
    if(app_bluetooth_setId(serial_device,"0002") < 0)
    {
        log_warn("app_bluetooth_setConnectionType set Bt id fail");
        return -1;
    }
    //设置段地址
    if(app_bluetooth_setAddr(serial_device,"4040") < 0)
    {
        log_warn("app_bluetooth_setConnectionType set Bt addr fail");
        return -1;
    }
     //串口端该成115200 再次尝试通信
    if(app_bluetooth_setBtBuad(serial_device,BT_Baud_115200) < 0)
    {
        log_warn("app_bluetooth_setConnectionType bt set fail");
        return -1;
    }
    //重启一下
    if(app_bluetooth_reset(serial_device) < 0)
     {
        log_warn("app_bluetooth_setConnectionType BT reset fail");
        return -1;
    }
    app_serial_setBaud(serial_device,Baud_115200);
    app_serial_setBlockMote(serial_device,1);
    app_serial_flush(serial_device);
    //设置配置
    serial_device->super.connect_type = CONNECT_BT; //蓝牙
    serial_device->super.vptr->post_read = app_bluetooth_psetRead;
    serial_device->super.vptr->post_write = app_bluetooth_psetWrite;
    log_trace("app_bluetooth init scuueed");
    return 0;
}


/**
 * 上游设备需要的格式
 * 字节1   connect_type 和下游司马类型设备连接
 * 字节2   id_len       id的长度
 * 字节3   mag_len      实际数据的长度
 * 字节4 ～  id + mag
 * 
 * 
 * 蓝牙接收的数据
 * 字节1～2  0XF1 0XDD  
 * 字节2     剩下的数据帧的长度
 * 字节3-4   对面的addr地质（也可以较id）
 * 字节5-6   我们的addr地址
 * 字节7～    实际数据
 * 
 * 
 * 蓝牙发送的数据
 * 字节 1-8 “AT+MESH\0”
 * 字节 9-10 对面ADDR
 * 字节 11-n 具体数据
 * 字节 n+1- n+2  "\r\n"
 */



/// @brief 这个函数用这把上游的通讯设备给出的数据变成我们这个蓝牙需要的格式
/// @param device 设备
/// @param buf 数据
/// @param len 数据的长度
/// @return 成功返回处理后的数据长度  失败返回-1
int app_bluetooth_psetWrite(Device *device,void *buf,int len)
{
    char * buffer = buf;
    log_trace("buffer  = %s",buffer);
    char bt_buff[128] = {0};
    //存储id长度 和 实际数据长度
    int id_len = 0;
    int mag_len = 0;
    memcpy(&id_len,buffer+1,1);
    memcpy(&mag_len,buffer+2,1);
    //判断数据是否正确
    if(id_len != 2)
    {
        log_warn("app_bluetooth_psetWrite data  length fail");
        //失败
        return -1;
    }
    //拼接数据
    memcpy(bt_buff,"AT+MESH",8);   // \0 也是他们蓝牙数据需要的格式 以及拷贝过去了
    memcpy(bt_buff + 8,buffer + 3,2); //拷贝id
    memcpy(bt_buff + 10,buffer + 5,mag_len);  //拷贝实际数据
    memcpy(bt_buff + 10 + mag_len,"\r\n",2);
    len = 12 + mag_len;
    memcpy(buf,bt_buff,len);
    return len;
}


/// @brief 这个函数用这把接收到的数据变成上有串口设备需要的数据格式
/// @param device 设备
/// @param buf 数据
/// @param len 数据的长度
/// @return 成功返回处理后的数据长度  失败返回-1
int app_bluetooth_psetRead(Device *device,void *buf,int len)
{
    //有可能传过来的数据不是一个完整的数据正  现用一个缓冲却存这个数据是一个完整的数据帧在发送
    memcpy(read_buffer,buf,len);
    //更性缓冲区长度
    read_buffer_leng += len;
    //判断数据是否有至少4个字节  OK\r\n  最少的数据格式  OK\r\n 我们不处理
    if(read_buffer_leng < 4)
    {
        log_warn("app_bluetooth_psetRead data  length fail");
        return -1;
    }
    //这是一个判断在缓冲区里面是否找到帧头的标志位
    int isFind = 0; //默认没有
    //i < read_buffer_leng - 3; 因为一条数据帧最少也是4个字节  通过没有找到说明里面还是没有我们需要的数据
    for(int i = 0 ; i < read_buffer_leng - 3;i++)
    {
        //查看有没有 OK\r\n 
        if(memcpy(read_buffer + i,"OK\r\n",4) == 0)
        {
            //找到了  但是我们不要这些数据 OK\r\n和前面的数据肯定都没有帧头全部不要了
            app_bluetoorh_ignore(i+4);
        }
        else if(memcmp(read_buffer + i,fixed_header,2) == 0)
        {
            //找到l 帧头  枕头前面的数据都不要了
            app_bluetoorh_ignore(i);
            isFind = 1;    //标志位
        }
    }

    //判断是否找到了枕头
    if(!isFind)
    {
        
        //失败
        return -1;
    }
    //存储read_buffer 中枕头和长度后面的实际数据长度
    int data_len = 0;
    memcpy(&data_len,read_buffer + 2,1);
    //判断readbuffer 里面的数据长度正确不 data_len(实际数据长度) + 2（帧头） + 1 （存储后面实际数据长度的）
    //如果缓存区的数据长度小于  上面 这个说明数据不全
    if(read_buffer_leng < data_len + 3)
    {
        log_warn("app_bluetooth_psetRead data partial");
        return -1;
    }

    unsigned char array[128] = {0};
    //数据正确
    memcpy(array,&device->connect_type,1); //类型
    array[1] = 2;   //id 长度 
    array[2] = data_len - 4;
    memcpy(array + 3,read_buffer + 7,array[2]);
    len = array[2] + 3;
    memcpy(buf,array,len);
    //清除读出的数据
    app_bluetoorh_ignore(len);
    return len;
}

